﻿using System.Text;
using System.Text.RegularExpressions;
using UnityEngine;

public enum EShowType
{
    active,
    layer,
    pos,
}

public enum ETransType
{
    Pos,
    Euler,
    Scale,
}

public enum EDirectType
{
    X,
    Y,
    Z,
}

public enum EPlatform
{
    None,
    Editor,
    Android,
    IPhone,
    StandAlone,
    WebPlayer,
}

public static class Utility
{
    static string pattern = "^[a-zA-Z$_]+[a-zA-Z0-9$_]*$";

    public static bool IsValidName(string objName)
    {
        return Regex.IsMatch(objName, pattern);
    }

    public static void SetLocalVector(Transform t, ETransType transType, EDirectType directType, float num)
    {
        Vector3 pos = GetLocalVector(t, transType);
        if (directType == EDirectType.X)
        {
            pos.x = num;
        }
        else if (directType == EDirectType.Y)
        {
            pos.y = num;
        }
        else if (directType == EDirectType.Z)
        {
            pos.z = num;
        }
        SetLocalVector(t, transType, pos);
    }

    public static float GetLocalVector(Transform t, ETransType transType, EDirectType directType)
    {
        Vector3 pos = GetLocalVector(t, transType);
        if (directType == EDirectType.X)
        {
            return pos.x;
        }
        else if (directType == EDirectType.Y)
        {
            return pos.y;
        }
        else if (directType == EDirectType.Z)
        {
            return pos.z;
        }
        return 0;
    }

    public static Vector3 GetLocalVector(Transform t, ETransType transType)
    {
        if (t == null) { return Vector3.zero; }
        if (transType == ETransType.Pos)
        {
            return t.localPosition;
        }
        else if (transType == ETransType.Euler)
        {
            return t.localEulerAngles;
        }
        else if (transType == ETransType.Scale)
        {
            return t.localScale;
        }
        return Vector3.zero;
    }

    public static void SetLocalVector(Transform t, ETransType transType, Vector3 vector)
    {
        if (t == null) { return; }
        if (transType == ETransType.Pos)
        {
            t.localPosition = vector;
        }
        else if (transType == ETransType.Euler)
        {
            t.localEulerAngles = vector;
        }
        else if (transType == ETransType.Scale)
        {
            t.localScale = vector;
        }
    }

    public static Vector3 GetWorldVector(Transform t, ETransType transType)
    {
        if (t == null) { return Vector3.zero; }
        if (transType == ETransType.Pos)
        {
            return t.position;
        }
        else if (transType == ETransType.Euler)
        {
            return t.eulerAngles;
        }
        return Vector3.zero;
    }

    public static void SetWorldVector(Transform t, ETransType transType, Vector3 vector)
    {
        if (t == null) { return; }
        if (transType == ETransType.Pos)
        {
            t.position = vector;
        }
        else if (transType == ETransType.Euler)
        {
            t.eulerAngles = vector;
        }
    }

    public static void SetActive(GameObject obj, EShowType nType, bool bActive)
    {
        if (nType == EShowType.active)
        {
            SetActive(obj, bActive);
        }
        else if (nType == EShowType.layer)
        {
            SetLayer(obj, bActive);
        }
        else if (nType == EShowType.pos)
        {
            SetPosition(obj, bActive);
        }
    }

    public static bool GetActive(GameObject obj, EShowType nType)
    {
        if (obj == null) { return false; }
        if (nType == EShowType.active)
        {
            return obj.activeInHierarchy;
        }
        else if (nType == EShowType.layer)
        {
            return obj.layer == LayerMask.NameToLayer("UI");
        }
        else if (nType == EShowType.pos)
        {
            return obj.transform.localPosition == Vector3.zero;
        }
        return false;
    }

    public static void SetActive(GameObject obj, bool bActive)
    {
        if (obj == null) { return; }
        if (obj.activeSelf != bActive)
        {
            obj.SetActive(bActive);
        }
    }

    public static void SetLayer(GameObject obj, bool bActive)
    {
        if (obj == null) { return; }
        if (bActive)
        {
            obj.layer = LayerMask.NameToLayer("UI");
        }
        else
        {
            obj.layer = LayerMask.NameToLayer("HideUI");
        }
    }

    public static void SetPosition(GameObject obj, bool bActive)
    {
        if (obj == null) { return; }
        if (bActive)
        {
            obj.transform.localPosition = Vector3.zero;
        }
        else
        {
            obj.transform.localPosition = new Vector3(-2048, 0, 0);
        }
    }

    public static void SetActive(this Component com, bool bActive)
    {
        if (com != null)
        {
            SetActive(com.gameObject, bActive);
        }
    }

    public static void SetBehaviour(this Behaviour behaviour, bool enabled)
    {
        if (behaviour == null) { return; }
        if (behaviour.enabled != enabled)
        {
            behaviour.enabled = enabled;
        }
    }

    public static void SetCollider(this Collider collider, bool enabled)
    {
        if (collider == null) { return; }
        if (collider.enabled != enabled)
        {
            collider.enabled = enabled;
        }
    }

    public static void SetBehaviour<T>(this Transform t, bool enabled) where T : Behaviour
    {
        if (t == null) { return; }
        for (int i = 0; i < t.childCount; i++)
        {
            Transform tf = t.GetChild(i);
            var behaviour = tf.GetComponent<T>();
            SetBehaviour(behaviour, enabled);
        }
    }

    public static void SetChildrenCollider(this Transform t, bool enabled)
    {
        if (t == null) { return; }
        for (int i = 0; i < t.childCount; i++)
        {
            Transform tf = t.GetChild(i);
            var collider = tf.GetComponent<Collider>();
            SetCollider(collider, enabled);
        }
    }

    public static void SetParent(GameObject parent, GameObject child)
    {
        if (child == null) { return; }
        Transform t = child.transform;
        t.localPosition = Vector3.zero;
        t.localRotation = Quaternion.identity;
        t.localScale = Vector3.one;

        if (parent == null) { return; }
        child.layer = parent.layer;
        t.parent = parent.transform;
    }

    /// <summary>
    /// 添加子节点对象
    /// </summary>
    /// <param name="parentObj">父级对象</param>
    /// <param name="prefab">创建对象</param>
    /// <param name="count">数量</param>
    /// <param name="func">回调</param>
    public static void AddChildren(this Component parentObj, GameObject prefab, int count,
        System.Action<GameObject, int> func = null)
    {
        Transform parent = parentObj.transform;
        for (int i = parent.childCount; i < count; i++)
        {
            AddChildren(prefab, parent);
        }

        for (int i = 0; i < parent.childCount; i++)
        {
            Transform child = parent.GetChild(i);
            child.gameObject.SetActive(i < count);

            if (i < count)
            {
                func?.Invoke(child.gameObject, i);
            }
        }
    }

    public static GameObject AddChildren(GameObject prefab, Component parentObj)
    {
        Transform parent = parentObj.transform;
        var go = Object.Instantiate(prefab, parent);
        go.layer = parentObj.gameObject.layer;

        int index = Mathf.Abs(go.GetInstanceID());
        go.name = $"{prefab.name}_{index}";
        go.transform.localPosition = Vector3.zero;
        return go;
    }

    public static string BuildTfPath(this Component com, Transform root)
    {
        if (com != null && root != null)
        {
            return BuildTfPath(com.transform, root);
        }
        return string.Empty;
    }

    public static string BuildTfPath(this Transform tf, Transform root = null)
    {
        var buffer = new StringBuilder();
        if (tf == null) { return buffer.ToString(); }

        while (tf != root)
        {
            if (buffer.Length > 0)
            {
                buffer.Insert(0, "/");
            }

            buffer.Insert(0, tf.name);
            tf = tf.parent;
        }
        return buffer.ToString();
    }

    public static string GetTypeFullName(this Object com)
    {
        if (com != null)
        {
            var type = com.GetType();
            return type.FullName;
        }
        return string.Empty;
    }

    public static string GetTypeName(this Object com)
    {
        if (com != null)
        {
            var type = com.GetType();
            return type.Name;
        }
        return string.Empty;
    }

    public static float AngerVector(Vector3 from, Vector3 to)
    {
        Vector3 v3 = Vector3.Cross(from, to);
        if (v3.y > 0)
        {
            return Vector3.Angle(from, to);
        }
        else
        {
            return -Vector3.Angle(from, to);
        }
    }

    /// <summary>
    /// 根节点相d对于root的localPosition,只针对root没有缩放的情况
    /// </summary>
    /// <param name="t"></param>
    public static Vector3 GetLocalPosition(Transform t)
    {
        if (t == null) { return Vector3.zero; }
        Vector3 pos = t.localPosition;

        for (; ; )
        {
            Transform parent = t.parent;
            if (parent == null) break;
            pos += parent.localPosition;
        }
        return pos;
    }

    /// <summary>
    /// 获取目标平台
    /// </summary>
    public static EPlatform GetPlatForm()
    {
#if UNITY_EDITOR
        return EPlatform.Editor;
#elif UNITY_ANDROID
        return EPlatform.Android;
#elif UNITY_IPHONE || UNITY_IOS
        return EPlatform.IPhone;
#elif UNITY_FLASH || UNITY_WEBPLAYER
        return EPlatform.WebPlayer;
#elif UNITY_STANDALONE
        return EPlatform.StandAlone;
#else
        return EPlatform.None;
#endif
    }
}